using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel.Design;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Shell;
using Microsoft.VisualStudio.Modeling.Diagrams;
using System.Data;
using CORIDemo;
using GuavaLib;
using GuavaData;
using System.Reflection;
using System.Collections;


namespace Guava.ChannelTransformations
{
    internal partial class ChannelTransformationsCommandSet
    {

        private const int InsertVSplit = 0x801;
        private const int InsertHMerge = 0x802;
        private const int InsertVMerge = 0x803;
        private const int InsertHSplit = 0x804;
        private const int InsertApply = 0x805;
        private const int InsertAudit = 0x806;
        private const int InsertRenameColumn = 0x807;
        private const int InsertPivot = 0x808;
        private const int InsertUnpivot = 0x809;
        private const int InsertAdorn = 0x810;
        private const int InsertRenameTable = 0x813;

        private const int ShowGTree = 0x811;
        private const int GenerateCSharpCode = 0x812;

        protected override void ProcessOnStatusDeleteCommand(System.ComponentModel.Design.MenuCommand cmd)
        {
            foreach (object selectedObject in this.CurrentSelection)
            {
                // selectedObject will be a Shape or Connector
                FlowConnector connector = selectedObject as FlowConnector;
                if (connector != null)     
                {
                    cmd.Enabled = false;
                    cmd.Visible = false;
                }
                else
                {
                    cmd.Enabled = true;
                    cmd.Visible = true;


                    //no delete for start and end operators
                    StartShape start = selectedObject as StartShape;
                    if (start != null)
                    {
                        cmd.Enabled = false;
                        cmd.Visible = false;
                    }
                    EndShape end = selectedObject as EndShape;
                    if (end != null)
                    {
                        cmd.Enabled = false;
                        cmd.Visible = false;
                    }

                }

            }
        }
        protected override global::System.Collections.Generic.IList<global::System.ComponentModel.Design.MenuCommand> GetMenuCommands()
        {//for context menu commands

            IList<MenuCommand> commands = base.GetMenuCommands();

            commands.Add(new DynamicStatusMenuCommand(
                new EventHandler(OnStatusChangeAssociationSort),
                new EventHandler(OnMenuChangeAssociationSort),
                new CommandID(new Guid(Constants.ChannelTransformationsCommandSetId), InsertVSplit)));

            commands.Add(new DynamicStatusMenuCommand(
                new EventHandler(OnStatusChangeAssociationSort),
                new EventHandler(OnMenuChangeAssociationSort),
                new CommandID(new Guid(Constants.ChannelTransformationsCommandSetId), InsertHMerge)));

            commands.Add(new DynamicStatusMenuCommand(
                new EventHandler(OnStatusChangeAssociationSort),
                new EventHandler(OnMenuChangeAssociationSort),
                new CommandID(new Guid(Constants.ChannelTransformationsCommandSetId), InsertHSplit)));

            commands.Add(new DynamicStatusMenuCommand(
                new EventHandler(OnStatusChangeAssociationSort),
                new EventHandler(OnMenuChangeAssociationSort),
                new CommandID(new Guid(Constants.ChannelTransformationsCommandSetId), InsertVMerge)));

            commands.Add(new DynamicStatusMenuCommand(
                new EventHandler(OnStatusChangeAssociationSort),
                new EventHandler(OnMenuChangeAssociationSort),
                new CommandID(new Guid(Constants.ChannelTransformationsCommandSetId), InsertApply)));

            commands.Add(new DynamicStatusMenuCommand(
                new EventHandler(OnStatusChangeAssociationSort),
                new EventHandler(OnMenuChangeAssociationSort),
                new CommandID(new Guid(Constants.ChannelTransformationsCommandSetId), InsertAudit)));

            commands.Add(new DynamicStatusMenuCommand(
               new EventHandler(OnStatusChangeAssociationSort),
               new EventHandler(OnMenuChangeAssociationSort),
               new CommandID(new Guid(Constants.ChannelTransformationsCommandSetId), InsertAdorn)));

            commands.Add(new DynamicStatusMenuCommand(
               new EventHandler(OnStatusChangeAssociationSort),
               new EventHandler(OnMenuChangeAssociationSort),
               new CommandID(new Guid(Constants.ChannelTransformationsCommandSetId), InsertPivot)));
            commands.Add(new DynamicStatusMenuCommand(
               new EventHandler(OnStatusChangeAssociationSort),
               new EventHandler(OnMenuChangeAssociationSort),
               new CommandID(new Guid(Constants.ChannelTransformationsCommandSetId), InsertUnpivot)));

            commands.Add(new DynamicStatusMenuCommand(
               new EventHandler(OnStatusChangeAssociationSort),
               new EventHandler(OnMenuChangeAssociationSort),
               new CommandID(new Guid(Constants.ChannelTransformationsCommandSetId), InsertRenameColumn)));
            commands.Add(new DynamicStatusMenuCommand(
               new EventHandler(OnStatusChangeAssociationSort),
               new EventHandler(OnMenuChangeAssociationSort),
               new CommandID(new Guid(Constants.ChannelTransformationsCommandSetId), InsertRenameTable)));

            commands.Add(new DynamicStatusMenuCommand(
            new EventHandler(OnStatusChangeAssociationSort),
            new EventHandler(OnMenuChangeAssociationSort),
            new CommandID(new Guid(Constants.ChannelTransformationsCommandSetId), ShowGTree)));

            commands.Add(new DynamicStatusMenuCommand(
            new EventHandler(OnStatusChangeAssociationSort),
            new EventHandler(OnMenuChangeAssociationSort),
            new CommandID(new Guid(Constants.ChannelTransformationsCommandSetId), GenerateCSharpCode)));


            return commands;

        }

#region context menu action code *************************
        //event fired when right clicked on any shape
        internal void OnStatusChangeAssociationSort(object sender, EventArgs e)
        {
            MenuCommand command = sender as MenuCommand;

            foreach (object selectedObject in this.CurrentSelection)
            {
                // selectedObject will be a Shape or Connector

                FlowConnector connector = selectedObject as FlowConnector;
                if (connector == null)
                    command.Visible = command.Enabled = false;
                else
                    if(connector != null)
                        command.Visible = command.Enabled = true;
                
                if ((connector != null) && (command.CommandID.ID == GenerateCSharpCode))
                    command.Visible = command.Enabled = false;
                else
                    if ((connector == null) && (command.CommandID.ID == GenerateCSharpCode))
                     command.Visible = command.Enabled = false;

                ChannelLane ch = selectedObject as ChannelLane;
                if ((ch != null) && (command.CommandID.ID == GenerateCSharpCode))
                    command.Visible = command.Enabled = true;

                SwimLane1 gs = selectedObject as SwimLane1;
                if ((gs != null))
                    command.Visible = command.Enabled = false; 
                
            }

        }
        internal void OnMenuChangeAssociationSort(object sender, EventArgs e)
        {
            MenuCommand command = sender as MenuCommand;
            foreach (object selectedObject in this.CurrentSelection)
            {
                ChannelLane ch = selectedObject as ChannelLane;
                if ((ch != null)&& (command.CommandID.ID == GenerateCSharpCode))
                {
                  GenerateCSharpCodeForModel(ch.Subject as Channel);
                  return;
                }
                //for all other commands
                // selectedObject will be a Shape or Connector
                FlowConnector connector = selectedObject as FlowConnector;
                if (connector == null) continue;

                Flow association = connector.Subject as Flow;
                if (association == null) continue;

                Operators opSource = association.FlowFrom;
                Operators opTarget = association.FlowTo;
                Operators sourceOperators1 = null;

                switch (command.CommandID.ID)
                {
                    case ShowGTree:
                        ShowGTreeForDomainModel(association.FlowFrom.Channel as Channel, opSource, opTarget);
                        return;
                    case InsertVSplit:
                        sourceOperators1 = AddOperator(association.FlowFrom, "VSplit", connector.Center);
                        break;
                    case InsertHMerge:
                        sourceOperators1 = AddOperator(association.FlowFrom, "HMerge", connector.Center);
                        break;
                    case InsertVMerge:
                        sourceOperators1 = AddOperator(association.FlowFrom, "VMerge", connector.Center);
                        break;
                    case InsertHSplit:
                        sourceOperators1 = AddOperator(association.FlowFrom, "HSplit", connector.Center);
                        break;
                    case InsertApply:
                        sourceOperators1 = AddOperator(association.FlowFrom, "Apply", connector.Center);
                        break;
                    case InsertAudit:
                        sourceOperators1 = AddOperator(association.FlowFrom, "Audit", connector.Center);
                        break;
                    case InsertAdorn:
                        sourceOperators1 = AddOperator(association.FlowFrom, "Adorn", connector.Center);
                        break;
                    case InsertRenameColumn:
                        sourceOperators1 = AddOperator(association.FlowFrom, "RenameColumn", connector.Center);
                        break;
                    case InsertRenameTable:
                        sourceOperators1 = AddOperator(association.FlowFrom, "RenameTable", connector.Center);
                        break;
                    case InsertPivot:
                        sourceOperators1 = AddOperator(association.FlowFrom, "Pivot", connector.Center);
                        break;
                    case InsertUnpivot:
                        sourceOperators1 = AddOperator(association.FlowFrom, "Unpivot", connector.Center);
                        break;
                }
                using (Transaction t = opSource.Store.TransactionManager.BeginTransaction())
                {
                    opSource.FlowTo.Clear();
                    opTarget.FlowFrom = null;

                    if (sourceOperators1 != null)
                    {
                        sourceOperators1.FlowTo.Add(opTarget);
                        sourceOperators1.FlowFrom = opSource;
                        t.Commit();
                        break;
                    }
                }

            }
        }
#endregion
        private Operators AddOperator(global::Guava.ChannelTransformations.Operators source, String AddElement, PointD insertPoint)
        {
            // All updates must be done inside a transaction
            int index = source.Channel.Operator.Count;

            using (Transaction t = source.Store.TransactionManager.BeginTransaction())
            {
                switch (AddElement)
                {
                    case "VSplit":
                        source.Store.LoadDomainModels(typeof(ChannelTransformationsDomainModel));
                        VSplit op1 = new VSplit(source.Store);
                        op1.Name = "VSplit" + index.ToString();
                        source.Channel.Operator.Add(op1);
                        t.Commit();

                        using (Transaction pos = source.Store.TransactionManager.BeginTransaction())
                        {
                            LinkedElementCollection<PresentationElement> presentations = PresentationViewsSubject.GetPresentation(op1);
                            VSplitShape shape = presentations[0] as VSplitShape;
                            RectangleD r = new RectangleD(2, insertPoint.Y, shape.Bounds.Width, shape.Bounds.Height);
                            shape.Bounds = r; //shape.BoundsRules.GetCompliantBounds(shape, r);
                            pos.Commit();
                        }

                        return op1;

                    case "HMerge":
                        source.Store.LoadDomainModels(typeof(ChannelTransformationsDomainModel));
                        HMerge op2 = new HMerge(source.Store);
                        op2.Name = "HMerge" + index.ToString();
                        source.Channel.Operator.Add(op2);
                        t.Commit();
                        using (Transaction pos = source.Store.TransactionManager.BeginTransaction())
                        {
                            LinkedElementCollection<PresentationElement> presentations = PresentationViewsSubject.GetPresentation(op2);
                            HMergeShape shape = presentations[0] as HMergeShape;
                            RectangleD r = new RectangleD(2, insertPoint.Y, shape.Bounds.Width, shape.Bounds.Height);
                            shape.Bounds = r; //shape.BoundsRules.GetCompliantBounds(shape, r);

                            pos.Commit();
                        }
                        return op2;
                    case "HSplit":
                        source.Store.LoadDomainModels(typeof(ChannelTransformationsDomainModel));
                        HSplit op3 = new HSplit(source.Store);
                        op3.Name = "HSplit" + index.ToString();
                        source.Channel.Operator.Add(op3);
                        t.Commit();
                        using (Transaction pos = source.Store.TransactionManager.BeginTransaction())
                        {
                            LinkedElementCollection<PresentationElement> presentations = PresentationViewsSubject.GetPresentation(op3);
                            HSplitShape shape = presentations[0] as HSplitShape;
                            RectangleD r = new RectangleD(2, insertPoint.Y, shape.Bounds.Width, shape.Bounds.Height);
                            shape.Bounds = r; //shape.BoundsRules.GetCompliantBounds(shape, r);

                            pos.Commit();
                        }
                        return op3;
                    case "VMerge":
                        source.Store.LoadDomainModels(typeof(ChannelTransformationsDomainModel));
                        VMerge op4 = new VMerge(source.Store);
                        op4.Name = "VMerge" + index.ToString();
                        source.Channel.Operator.Add(op4);
                        t.Commit();
                        using (Transaction pos = source.Store.TransactionManager.BeginTransaction())
                        {
                            LinkedElementCollection<PresentationElement> presentations = PresentationViewsSubject.GetPresentation(op4);
                            VMergeShape shape = presentations[0] as VMergeShape;
                            RectangleD r = new RectangleD(2, insertPoint.Y, shape.Bounds.Width, shape.Bounds.Height);
                            shape.Bounds = r; //shape.BoundsRules.GetCompliantBounds(shape, r);

                            pos.Commit();
                        }
                        return op4;
                    case "Audit":
                        source.Store.LoadDomainModels(typeof(ChannelTransformationsDomainModel));
                        Audit op5 = new Audit(source.Store);
                        op5.Name = "Audit" + index.ToString();
                        source.Channel.Operator.Add(op5);
                        t.Commit();
                        using (Transaction pos = source.Store.TransactionManager.BeginTransaction())
                        {
                            LinkedElementCollection<PresentationElement> presentations = PresentationViewsSubject.GetPresentation(op5);
                            AuditShape shape = presentations[0] as AuditShape;
                            RectangleD r = new RectangleD(2, insertPoint.Y, shape.Bounds.Width, shape.Bounds.Height);
                            shape.Bounds = r; //shape.BoundsRules.GetCompliantBounds(shape, r);

                            pos.Commit();
                        }
                        return op5;
                    case "Apply":
                        source.Store.LoadDomainModels(typeof(ChannelTransformationsDomainModel));
                        Apply op6 = new Apply(source.Store);
                        op6.Name = "Apply" + index.ToString();
                        source.Channel.Operator.Add(op6);
                        t.Commit();
                        using (Transaction pos = source.Store.TransactionManager.BeginTransaction())
                        {
                            LinkedElementCollection<PresentationElement> presentations = PresentationViewsSubject.GetPresentation(op6);
                            ApplyShape shape = presentations[0] as ApplyShape;
                            RectangleD r = new RectangleD(2, insertPoint.Y, shape.Bounds.Width, shape.Bounds.Height);
                            shape.Bounds = r; //shape.BoundsRules.GetCompliantBounds(shape, r);

                            pos.Commit();
                        }
                        return op6;
                    case "Adorn":
                        source.Store.LoadDomainModels(typeof(ChannelTransformationsDomainModel));
                        Adorn op7 = new Adorn(source.Store);
                        op7.Name = "Adorn" + index.ToString();
                        source.Channel.Operator.Add(op7);
                        t.Commit();
                        using (Transaction pos = source.Store.TransactionManager.BeginTransaction())
                        {
                            LinkedElementCollection<PresentationElement> presentations = PresentationViewsSubject.GetPresentation(op7);
                            AdornShape shape = presentations[0] as AdornShape;
                            RectangleD r = new RectangleD(2, insertPoint.Y, shape.Bounds.Width, shape.Bounds.Height);
                            shape.Bounds = r; //shape.BoundsRules.GetCompliantBounds(shape, r);

                            pos.Commit();
                        }
                        return op7;
                    case "Pivot":
                        source.Store.LoadDomainModels(typeof(ChannelTransformationsDomainModel));
                        Pivot op8 = new Pivot(source.Store);
                        op8.Name = "Pivot" + index.ToString();
                        source.Channel.Operator.Add(op8);
                        t.Commit();
                        using (Transaction pos = source.Store.TransactionManager.BeginTransaction())
                        {
                            LinkedElementCollection<PresentationElement> presentations = PresentationViewsSubject.GetPresentation(op8);
                            PivotShape shape = presentations[0] as PivotShape;
                            RectangleD r = new RectangleD(2, insertPoint.Y, shape.Bounds.Width, shape.Bounds.Height);
                            shape.Bounds = r; //shape.BoundsRules.GetCompliantBounds(shape, r);

                            pos.Commit();
                        }
                        return op8;
                    case "Unpivot":
                        source.Store.LoadDomainModels(typeof(ChannelTransformationsDomainModel));
                        Unpivot op9 = new Unpivot(source.Store);
                        op9.Name = "Unpivot" + index.ToString();
                        source.Channel.Operator.Add(op9);
                        t.Commit();
                        using (Transaction pos = source.Store.TransactionManager.BeginTransaction())
                        {
                            LinkedElementCollection<PresentationElement> presentations = PresentationViewsSubject.GetPresentation(op9);
                            UnpivotShape shape = presentations[0] as UnpivotShape;
                            RectangleD r = new RectangleD(2, insertPoint.Y, shape.Bounds.Width, shape.Bounds.Height);
                            shape.Bounds = r; //shape.BoundsRules.GetCompliantBounds(shape, r);

                            pos.Commit();
                        }
                        return op9;
                    case "RenameColumn":
                        source.Store.LoadDomainModels(typeof(ChannelTransformationsDomainModel));
                        RenameColumn op10 = new RenameColumn(source.Store);
                        op10.Name = "RenameColumn" + index.ToString();
                        source.Channel.Operator.Add(op10);
                        t.Commit();
                        using (Transaction pos = source.Store.TransactionManager.BeginTransaction())
                        {
                            LinkedElementCollection<PresentationElement> presentations = PresentationViewsSubject.GetPresentation(op10);
                            RenameColumnShape shape = presentations[0] as RenameColumnShape;
                            RectangleD r = new RectangleD(2, insertPoint.Y, shape.Bounds.Width, shape.Bounds.Height);
                            shape.Bounds = r; //shape.BoundsRules.GetCompliantBounds(shape, r);

                            pos.Commit();
                        }
                        return op10;
                    case "RenameTable":
                        source.Store.LoadDomainModels(typeof(ChannelTransformationsDomainModel));
                        RenameTable op11 = new RenameTable(source.Store);
                        op11.Name = "RenameTable" + index.ToString();
                        source.Channel.Operator.Add(op11);
                        t.Commit();
                        using (Transaction pos = source.Store.TransactionManager.BeginTransaction())
                        {
                            LinkedElementCollection<PresentationElement> presentations = PresentationViewsSubject.GetPresentation(op11);
                            RenameTableShape shape = presentations[0] as RenameTableShape;
                            RectangleD r = new RectangleD(2, insertPoint.Y, shape.Bounds.Width, shape.Bounds.Height);
                            shape.Bounds = r; 

                            pos.Commit();
                        }
                        return op11;
                    default:
                        return null;
                }

            }
            return null;

        }

#region Gtree generation code *********************************************
        private void ShowGTreeForDomainModel(Channel ch,Operators source, Operators target)
        {
            Schema result = GetGTreeAtStartPoint(ch).ToSchema();
            object[] xSchemaParams = { result };

            //now apply all operators schema upto source.
            Operators origin = ch.Operator[0];
            Operators next = null;
            
            while (!(source.GetDomainClass().Name == "StartPoint"))
            { 
                next = origin.FlowTo[0];

                result = ApplyOperatorSchema(next, xSchemaParams,ch.OperatorPath);

                if (next != source)
                    origin = next;
                else
                    break;
            }
           DisplaySchema(ch, result);
       }

        private static Schema ApplyOperatorSchema(Operators next, object[] xSchemaParams,string operatorPath )
        {
            Assembly app = Assembly.LoadFrom(operatorPath);

            Type appType = app.GetType("GuavaData." + next.GetDomainClass().Name, true);
            
            //as the count is unknows , need a resizable list
            ArrayList paramList = new ArrayList();
            ArrayList paramTypeList = new ArrayList();

            for(int i = 0; i< next.GetDomainClass().AllDomainProperties.Count; i++)
            {
                DomainPropertyInfo di = next.GetDomainClass().AllDomainProperties[i];
                if ((di.Name == "ShowConfigIcon") || (di.Name == "Name")) continue;

                if (di.GetValue(next).GetType().Name == "ListType")
                {
                    Guava.ChannelTransformations.ListType temp = di.GetValue(next) as Guava.ChannelTransformations.ListType;
                    List<string> listypeParams = new List<string>();
                    for (int j = 0; j < temp.Count; j++)
                    {
                        listypeParams.Add(temp[j].Name);
                       
                    }
                    paramList.Add(listypeParams);
                    paramTypeList.Add(typeof(List<string>));
                    continue;
                }
                if (di.GetValue(next).GetType().Name == "MyDictionary")
                {
                    Guava.ChannelTransformations.MyDictionary temp = di.GetValue(next) as Guava.ChannelTransformations.MyDictionary;
                    Dictionary<string, string> dictTypeParams = new Dictionary<string, string>();
                    for (int j = 0; j < temp.Count; j++)
                    {
                        string current = temp[j].Name;      //string is tablename,oldcolumnname,newcolumnname format
                        string[] values = current.Split(new char[] { ',' });

                        try
                        {
                            if (next.GetType().Name == "RenameColumn")
                                dictTypeParams.Add(values[0] + "~" + values[1], values[2]);
                            else
                                dictTypeParams.Add(values[0], values[1]);
                        }
                        catch (Exception ee)
                        {
                            throw new Exception("The input string is not in a valid format");

                        }

                    }
                    paramList.Add(dictTypeParams);
                    paramTypeList.Add(typeof(Dictionary<string, string>));
                    continue;
                }
                if (di.GetValue(next).GetType().Name == "String")
                {
                    paramList.Add(di.GetValue(next).ToString());
                    paramTypeList.Add(typeof(string));
                }
                if (di.GetValue(next).GetType().Name == "Function")
                {//ex:for BitMask,CurrentTime, get the constructor and create

                    //get the function constructor
                    Type appType1 = app.GetType("GuavaData." + di.GetValue(next).ToString(), true);
                    ConstructorInfo[] ci1 = appType1.GetConstructors();

                    //Assumption: arguments to the function is next property if exists
                    DomainPropertyInfo argsProp = next.GetDomainClass().AllDomainProperties[i+1];
                    if ((argsProp != null) && (argsProp.Name == "FunctionArgs"))
                    { //get the arguments to function(these will be comma separated) and pass it to function constructor

                        string ArgumentsList = argsProp.GetValue(next).ToString();
                        ArrayList argvalues = new ArrayList();
                        string[] alist = ArgumentsList.Split(new char[] { ',' });
                        try
                        {
                            foreach (string a in alist)
                                argvalues.Add(int.Parse(a));
                        }
                        catch (Exception ee)
                        {
                            throw new Exception("Arguments list to the function is expected to be of integer values");      //may need make it more dynamic
                        }
                        object[] fparam = new object[alist.Length];
                        argvalues.CopyTo(fparam);
                        try
                        {
                            paramList.Add(ci1[0].Invoke(fparam));
                        }
                        catch (Exception ee)
                        {
                            throw new Exception("Arguments list to the function does not match expected type or order ");      //may need make it more dynamic
                        }
                        i++;
                    }
                    else
                    {

                        object[] fparam = null;
                        paramList.Add(ci1[0].Invoke(fparam));
                    }
                   
                    paramTypeList.Add(appType1);
                }
            }
            

            object[] paramValues = new object[paramList.Count];  
            Type[] paramTypes = new Type[paramTypeList.Count];  
            

            paramList.CopyTo(paramValues); //convert paramaters collection to pass it constructor
            paramTypeList.CopyTo(paramTypes);

            ConstructorInfo ci = appType.GetConstructor(paramTypes); 
             Object o ;
             try
             {
                 
                 o = ci.Invoke(paramValues);
             }
             catch (Exception ee)
             {
                 throw new Exception(ee.InnerException.Message);
             }

            MethodInfo mi = appType.GetMethod("XSchema");

            try
            {
                return ((Schema)mi.Invoke(o, xSchemaParams));
            }
            catch (Exception ee)
            {
                throw new Exception(ee.InnerException.Message);
            }
            
        }

        private static void DisplaySchema(Channel ch, Schema result)
        {
            String columnsText = "";
            TableToDisplay st;
            Scheme dt;

            //clear the gtree schema now 
            using (Transaction t = ch.Store.TransactionManager.BeginTransaction())
            {
                ch.TransformationRoot.Store.LoadDomainModels(typeof(ChannelTransformationsDomainModel));
                if (ch.TransformationRoot.GtreeSchema != null)
                    ch.TransformationRoot.GtreeSchema.Delete();
                t.Commit();
            }
           
            for (int j = 0; j < result.tables.Count; j++)
            {//create a table class and display its properties
                dt = result.tables[j];
                using (Transaction t = ch.Store.TransactionManager.BeginTransaction())
                {
                    ch.TransformationRoot.Store.LoadDomainModels(typeof(ChannelTransformationsDomainModel));

                    if (ch.TransformationRoot.GtreeSchema == null)
                        ch.TransformationRoot.GtreeSchema = new GtreeSchema(ch.TransformationRoot.Store);

                    //need to set the name of the scheme unique - it is identifier
                    
                    st = new TableToDisplay(ch.TransformationRoot.GtreeSchema.Store);
                    ch.TransformationRoot.GtreeSchema.SchemaTable.Add(st);

                    st.TableDisplayName = dt.TableName;
                    st.Name = "Scheme" + j;
                    columnsText = "";
                    string primaryColumns = "";
                    char[] separator = {' '};
                    
                    for (int i = 0; i < dt.columns.Count; i++)
                    {
                        GuavaData.Column dc = dt.columns[i];
                        if (dt.pkColumns.Contains(dc))
                        {
                            if (primaryColumns == "")
                                primaryColumns = primaryColumns + dc.ToString().Split(separator)[0];
                            else
                                primaryColumns = primaryColumns + ", " + dc.ToString().Split(separator)[0];
                        }
                        else
                            columnsText = columnsText + "\n" + dc.ToString().Split(separator)[0];
                                          
                    }
                    st.TableDisplayName = st.TableDisplayName + "(Pk:" + primaryColumns + ")";
                   // st.primaryColumns = primaryColumns;
                    st.Columns = columnsText;
                    t.Commit();
                }
            }
        }

        private static GTree GetGTreeAtStartPoint(Channel ch)
        {
            Assembly app;
            Type appType;
            ConstructorInfo ci;
            Object o;
            GTree gt;

            string className = ch.GtreeClassName;
            string path = ch.GtreePath;

            if ((path == "") || (className == ""))
                throw new Exception("Path and ClassName of channel can not be empty");

            // Pull the correct assembly
            app = Assembly.LoadFile(path);  //to do -it is loading from GAC instead of here 

            // Pull the Program class from the assembly
            appType = app.GetType(className, true);

            if (appType == null) throw new Exception("Could not find the appropriate entry point class in application.");

            // Initialize constructor
            ci = appType.GetConstructor(new Type[0]);

            o = ci.Invoke(new object[0]);

            gt = GTree.Generate((GuavaData.Guava)o);

            return gt;
        }


#endregion 
#region code generation methods*************************

        private void GenerateCSharpCodeForModel(Channel ch)  
        {

            String codeText = "using System;" +
                "\n" + "using System.Collections.Generic;" +
                "\n" + "using System.Text;" + "\n" + "using GuavaData;";
            codeText = codeText + "namespace CORIDemo" + "\n" +
                        "{" + "\n" +
                     " static class AppChannel" + "\n" +
                     "{" + "\n" +
                      " public static Channel GetChannel()" + "\n" +
                        "{" + "\n";

            codeText = codeText + "\n" + "Channel c = new Channel();" + "\n" ;

            int StartIndex = 0;
            int operatorNumber = 0;

            Operators op;

            //find the start point index(will be 0 for now) and then follow until end point
            for (int i = 0; i < ch.Operator.Count; i++)
            {
                if (ch.Operator[i].GetDomainClass().Id == StartPoint.DomainClassId)
                {
                    StartIndex = i;
                    break;
                }
            }

            op = ch.Operator[StartIndex].FlowTo[0];

            while (op.GetDomainClass().Id != EndPoint.DomainClassId)
            {
                operatorNumber++;
                //codeText = codeText + "\n";
                switch (op.GetDomainClass().Name)
                {
                    case "VSplit":
                        codeText = codeText + GetVSplitOperatorDetails(op as VSplit, operatorNumber);
                        
                        break;
                    case "HMerge":
                        codeText = codeText + GetHMergeOperatorDetails(op as HMerge, operatorNumber) + "\n" + "\t";
                        
                        break;
                    case "Pivot":
                        codeText = codeText + GetPivotOperatorDetails(op as Pivot, operatorNumber) + "\n" + "\t";
                        
                        break;
                    case "Unpivot":
                        codeText = codeText + GetUnpivotOperatorDetails(op as Unpivot, operatorNumber) + "\n" + "\t";
                        
                        break;
                    case "Apply":
                        codeText = codeText + GetApplyOperatorDetails(op as Apply, operatorNumber) + "\n" + "\t";
                        
                        break;
                    case "Audit":
                        codeText = codeText + GetAuditOperatorDetails(op as Audit, operatorNumber) + "\n" + "\t";
                        
                        break;
                    case "RenameColumn":
                        codeText = codeText + GetRenameColumnOperatorDetails(op as RenameColumn, operatorNumber) + "\n" + "\t";
                        break;
                    case "RenameTable":
                        codeText = codeText + GetRenameTableOperatorDetails(op as RenameTable, operatorNumber) + "\n" + "\t";
                        break;
                    case "VMerge":
                        codeText = codeText + GetVMergeOperatorDetails(op as VMerge, operatorNumber) + "\n" + "\t";
                        break;
                    case "HSplit":
                        codeText = codeText + GetHSplitOperatorDetails(op as HSplit, operatorNumber) + "\n" + "\t";
                        break;
                    case "Adorn":
                        codeText = codeText + GetAdornOperatorDetails(op as Adorn, operatorNumber) + "\n" + "\t";
                        break;
                    default:    //should not be coming here -just incase avoid loop
                        break;
                }
                codeText = codeText + "\n" + "c.Add(" + op.Name + ");" + "\n";
                op = op.FlowTo[0];
            }

            codeText = codeText + "\n" +
                               "return c;" + "\n" +
                         "}" + "\n" +
                    "}" + "\n" +
                "}" + "\n";
            
            //create the file and save the contents.
            System.Windows.Forms.MessageBox.Show(codeText);
        }

        private string GetHMergeOperatorDetails(HMerge hMergeOp, int operatorNumber)
        {
        
            string operator_details = "";
            operator_details = operator_details + "\n" + "List<string> ";
            operator_details = operator_details + hMergeOp.Name + "_tables = new List<string>();" + "\n";
            for (int i = 0; i < hMergeOp.tablesToMerge.Count; i++)
                operator_details = operator_details + hMergeOp.Name + "_tables.Add(\"" +
                    hMergeOp.tablesToMerge[i].Name + "\");" + "\n";


            operator_details = operator_details + "HMerge" + "  " + "myOperator" + operatorNumber + " = ";
            operator_details = operator_details + "new HMerge(\"" + hMergeOp.inName + "\", ";
            operator_details = operator_details + hMergeOp.Name + "_tables" + ", ";
            operator_details = operator_details + "\"" + hMergeOp.newColumn + "\");";

            
            return (operator_details);

        }

        private string GetPivotOperatorDetails(Pivot pivotOp, int operatorNumber)
        {
           

            string operator_details = "";
            operator_details = operator_details + "\n" + "List<string> ";
            operator_details = operator_details + pivotOp.Name + "_tables = new List<string>();" + "\n";
            for (int i = 0; i < pivotOp.tables.Count; i++)
                operator_details = operator_details + pivotOp.Name + "_tables.Add(\"" +
                    pivotOp.tables[i].Name + "\");" + "\n";

            operator_details = operator_details +  "List<string> ";
            operator_details = operator_details + pivotOp.Name + "_attrList = new List<string>();" + "\n";
            for (int i = 0; i < pivotOp.attrColumns.Count; i++)
                operator_details = operator_details + pivotOp.Name + "_attrList.Add(\"" +
                    pivotOp.attrColumns[i].Name + "\");" + "\n";

            operator_details = operator_details +  "List<string> ";
            operator_details = operator_details + pivotOp.Name + "_valList = new List<string>();" + "\n";
            for (int i = 0; i < pivotOp.valColumns.Count; i++)
                operator_details = operator_details + pivotOp.Name + "_valList.Add(\"" +
                    pivotOp.valColumns[i].Name + "\");" + "\n";

            operator_details = operator_details + "Pivot" + "  " + "myOperator" + operatorNumber + " = ";
            operator_details = operator_details + "new Pivot(" + pivotOp.Name + "_tables" + ", ";
            operator_details = operator_details + pivotOp.Name + "_attrList" + ", ";
            operator_details = operator_details +  pivotOp.Name + "_valList);";

           
            return (operator_details);
        }

        private string GetUnpivotOperatorDetails(Unpivot unpivotOp, int operatorNumber)
        {
            string operator_details = "";
            operator_details = operator_details + "List<string> ";
            operator_details = operator_details + unpivotOp.Name + "_tables = new List<string>();" + "\n";
            for (int i = 0; i < unpivotOp.UnpivotTables.Count; i++)
                operator_details = operator_details + unpivotOp.Name + "_tables.Add(\"" + unpivotOp.UnpivotTables[i].Name + "\");" + "\n";


            operator_details = operator_details + "Unpivot" + "  " + "myOperator" + operatorNumber + " = ";
            operator_details = operator_details + "new Unpivot(" + unpivotOp.Name + "_tables"
                                                                 + ");";

            return (operator_details);
        }

        private string GetApplyOperatorDetails(Apply applyOp, int operatorNumber)
        {
            string operator_details = "";
            operator_details = operator_details + "\n" + "List<string> ";
            operator_details = operator_details + applyOp.Name + "_inNames = new List<string>();" + "\n";
            for (int i = 0; i < applyOp.inNames.Count; i++)
                operator_details = operator_details + applyOp.Name + "_inNames.Add(\"" +
                    applyOp.inNames[i].Name + "\");" + "\n";

            operator_details = operator_details + "List<string> ";
            operator_details = operator_details + applyOp.Name + "_outNames = new List<string>();" + "\n";
            for (int i = 0; i < applyOp.outNames.Count; i++)
                operator_details = operator_details + applyOp.Name + "_outNames.Add(\"" +
                    applyOp.outNames[i].Name + "\");" + "\n";


            operator_details = operator_details + "Apply" + "  " + "myOperator" + operatorNumber  + " = ";
            operator_details = operator_details + "new Apply( new " + applyOp.ApplyFunction.ToString() + "( " ;
            operator_details = operator_details + applyOp.FunctionArgs.ToString()  + "), ";
            operator_details = operator_details + "\"" + applyOp.table + "\",";
            operator_details = operator_details + applyOp.Name + "_inNames" + ", ";
            operator_details = operator_details + applyOp.Name + "_outNames);" ;
            


            return (operator_details);
        }

        private string GetAuditOperatorDetails(Audit auditOp, int operatorNumber)
        {
            string operator_details = "";
            operator_details = operator_details + "List<string> ";
            operator_details = operator_details + auditOp.Name + "_tables = new List<string>();" + "\n";
            for (int i = 0; i < auditOp.TablesToAudit.Count; i++)
                operator_details = operator_details + auditOp.Name + "_tables.Add(\"" + auditOp.TablesToAudit[i].Name + "\");" + "\n";


            operator_details = operator_details + "Audit" + "  " + "myOperator" + operatorNumber + " = ";
            operator_details = operator_details + "new Audit(" + auditOp.Name + "_tables"
                                                                + ");";

            return (operator_details);

        }

        private string GetRenameColumnOperatorDetails(RenameColumn renameColumnOp, int operatorNumber)
        {

            string operator_details = "";
            operator_details = operator_details + "Dictionary<string, string> " + renameColumnOp.Name + "_input" + " = new Dictionary<string, string>();\n";
            for (int i = 0; i < renameColumnOp.TableCurrentColmunNewColumn.Count; i++)
            {
                string current = renameColumnOp.TableCurrentColmunNewColumn[i].Name;      //string is tablename,oldcolumnname,newcolumnname format
                string[] values = current.Split(new char[] { ',' });
                operator_details = operator_details + renameColumnOp.Name + "_input.Add" + "(\"" + values[0] + "~" + values[1] + "\",\" " + values[1] + "\");";
                
            }
            operator_details = operator_details + "\n";
            operator_details = operator_details + "RenameColumn" + "  " + "myOperator" + operatorNumber + " = ";
            operator_details = operator_details + "new RenameColumn(" + renameColumnOp.Name + "_input" + ");";

            return (operator_details);

        }
        private string GetRenameTableOperatorDetails(RenameTable renameTableOp, int operatorNumber)
        {

            string operator_details = "";
            
            operator_details = operator_details + "Dictionary<string, string> " + renameTableOp.Name + "_input" + " = new Dictionary<string, string>();\n";

            for (int i = 0; i < renameTableOp.CurrentTableNewTable.Count; i++)
            {
                string current = renameTableOp.CurrentTableNewTable[i].Name;      //string is tablename,oldcolumnname,newcolumnname format
                string[] values = current.Split(new char[] { ',' });

                operator_details = operator_details + renameTableOp.Name + "_input.Add" + "(\"" + values[0] + "\",\" " + values[1] + "\");";
            }


            operator_details = operator_details + "\n";
            operator_details = operator_details + "RenameTable" + "  " + "myOperator" + operatorNumber + " = ";
            operator_details = operator_details + "new RenameTable(" + renameTableOp.Name + "_input" + ");";

            return (operator_details);

        }

        private string GetVMergeOperatorDetails(VMerge vMergeOp, int operatorNumber)
        {
            string operator_details = "";

            operator_details = operator_details + "VMerge" + "  " + "myOperator" + operatorNumber + " = ";
            operator_details = operator_details + "new VMerge(";
            operator_details = operator_details + "\"" + vMergeOp.LeftTable + "\"," +
                                          "\"" + vMergeOp.RightTable + "\"" + ");";

            return (operator_details);
        }

        private string GetHSplitOperatorDetails(HSplit hSplit, int operatorNumber)
        {
            string operator_details = "";

            operator_details = operator_details + "HSplit" + "  " + "myOperator" + operatorNumber + " = ";
            operator_details = operator_details + "new HSplit(" + hSplit.Name + ");";

            return (operator_details);
        }

        private string GetVSplitOperatorDetails(VSplit vsplitOp, int operatorNumber)
        {
            string operator_details = "";
            operator_details = operator_details + "List<string> ";
            operator_details = operator_details + vsplitOp.Name + "_columns = new List<string>();" + "\n";
            for (int i = 0; i < vsplitOp.columnsToSplit.Count; i++)
                operator_details = operator_details + vsplitOp.Name + "_columns.Add(\"" + vsplitOp.columnsToSplit[i].Name + "\");" + "\n";

            operator_details = operator_details + "VSplit" + "  " + "myOperator" + operatorNumber + " = ";
            operator_details = operator_details + "new VSplit(\"" + vsplitOp.table + "\", ";
            operator_details = operator_details + "\"" + vsplitOp.newTable + "\", ";
            operator_details = operator_details + vsplitOp.Name + "_columns" + ");";

            return (operator_details);

        }
        private string GetAdornOperatorDetails(Adorn adornOp, int operatorNumber)
        {
            string operator_details = "";
            operator_details = operator_details + "List<string> ";
            operator_details = operator_details + adornOp.Name + "_tables = new List<string>();" + "\n";
            for (int i = 0; i < adornOp.tablesToAdorn.Count; i++)
                operator_details = operator_details + adornOp.Name + "_tables.Add(\"" +
                    adornOp.tablesToAdorn[i].Name + "\");" + "\n";


            operator_details = operator_details + "Adorn" + "  " + "myOperator" + operatorNumber + " = ";
            operator_details = operator_details + "new Adorn(" + adornOp.Name + "_tables" + ", ";
            operator_details = operator_details + "\"" + adornOp.newColumn + "\", ";
            operator_details = operator_details + "new " +  adornOp.Adorner.ToString() +  "());";



            return (operator_details);

        }

#endregion ****************************************************************

    }     
}

   